package com.sd.repay.service.impl;

import com.sd.repay.common.CommonResult;
import com.sd.repay.common.Constants;
import com.sd.repay.dao.BaseDao;
import com.sd.repay.pojo.ExtractionOrder;
import com.sd.repay.pojo.TransferOrder;
import com.sd.repay.pojo.WithdrawOrder;
import com.sd.repay.service.BalanceOperService;
import com.sd.repay.service.CashService;
import com.sd.repay.service.ExtractOrderService;
import com.sd.repay.service.WithdrawOrderService;
import com.sd.repay.transfer.Transfer;
import com.sd.repay.utils.SpringUtil;
import com.sd.repay.utils.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by sd on 2018/10/16.
 */
@Service
public class CashServiceImpl implements CashService {

    private static final Logger log = LoggerFactory.getLogger(CashServiceImpl.class);

    @Autowired
    private BaseDao baseDao;
    @Autowired
    private ExtractOrderService extractService;
    @Autowired
    private WithdrawOrderService withdrawService;
    @Autowired
    private BalanceOperService balanceOperService;

    /**
     * 发起提现
     *
     * @param extOrder
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public CommonResult postalCash(ExtractionOrder extOrder) throws Exception {

        String merType = extOrder.getMerType();
        String merNo = extOrder.getMerNo();
        String extOrderNo = extOrder.getOrderNo();
        //新增提现记录
        int count = extractService.saveExtractOrder(extOrder);
        log.info("提现用户类型[{}]用户编号[{}]新增提现记录[{}]影响的行数[{}]", new Object[]{merType, merNo, extOrderNo, count});
        if (count < 1) {
            return CommonResult.build(403, "提现失败，请稍候再试");
        }
        //新增统一出账记录
        WithdrawOrder withdrawOrder = new WithdrawOrder();
        String withdrawOrderNo = WebUtil.nextUniqueSeqNo("t_withdraw_order", "TWOR", 25);
        withdrawOrder.setOrderNo(withdrawOrderNo);
        withdrawOrder.setMerType(extOrder.getMerType());
        withdrawOrder.setMerNo(extOrder.getMerNo());
        withdrawOrder.setService(Constants.WITHDRAW_SERVICE_WITHDRAW);
        withdrawOrder.setServiceOrderNo(extOrderNo);
        withdrawOrder.setAcqCode(extOrder.getAcqCode());
        withdrawOrder.setCardNo(extOrder.getCardNo());
        withdrawOrder.setAccountNo(extOrder.getAccountNo());
        withdrawOrder.setAccountName(extOrder.getAccountName());
        withdrawOrder.setAccountName(extOrder.getAccountName());
        withdrawOrder.setAmount(extOrder.getAmount());
        withdrawOrder.setFee(extOrder.getFee());
        count = withdrawService.saveWithdrawOrder(withdrawOrder);
        log.info("提现用户类型[{}]用户编号[{}]新增统一出账记录[{}]影响的行数[{}]", new Object[]{merType, merNo, withdrawOrderNo, count});
        if (count < 1) {
            throw new RuntimeException("用户类型" + merType + "用户编号" + merNo + "提现新增统一出账记录失败");
        }
        //更新用户余额信息(提现只能走纯代付通道)
        boolean isUpdateBalance = true;
        try {
            String balanceRemark = "用户类型" + merType + "用户编号" + merNo + "订单" + extOrderNo + "提现";
            CommonResult balanceRes = balanceOperService.updateBalance(merNo, merType, extOrder.getAmount(), Constants.BALANCE_HIS_TRANS_TYPE_OUT, Constants.BALANCE_HIS_TYPE_CURR,
                    Constants.BALANCE_HIS_SERVICE_CASH, extOrderNo, balanceRemark, Constants.BALANCE_CHANNEL_DAIFU);
            if (balanceRes == null || balanceRes.getStatus() != 200) {
                isUpdateBalance = false;
            }
        } catch (Exception e) {
            log.error("用户类型" + merType + "用户编号" + merNo + "提现更新余额异常" + e);
            isUpdateBalance = false;
        }
        if (!isUpdateBalance) {
            //跟新提现订单记录和统一出账订单记录
            count = withdrawService.writeBackWithdrawInfo(withdrawOrderNo, Constants.WITHDRAW_STATUS_FAIL, null, null, "", "提现更新余额异常");
            log.info("用户类型" + merType + "用户编号" + merNo + "提现更新余额失败，修改统一出账订单" + withdrawOrderNo + "状态失败影响的行数" + count);
            count = extractService.updateExtractStatus(extOrderNo, Constants.EXTRACT_STATUS_FAIL, null, Constants.EXTRACT_IS_NOT_REVERSE, "", "", "提现更新余额异常");
            log.info("用户类型" + merType + "用户编号" + merNo + "提现更新余额失败，修改提现订单" + extOrderNo + "状态失败影响的行数" + count);

            return CommonResult.build(403, "提现失败，请稍候再试");
        }

        //余额跟新成功，发起提现接口
        TransferOrder payTransfer = new TransferOrder();
        payTransfer.setTradeSource(extOrder.getAcqCode());
        payTransfer.setOrderType(Constants.WITHDRAW_SERVICE_WITHDRAW);
        payTransfer.setSourceOrderNo(withdrawOrderNo);
        payTransfer.setInAccNo(extOrder.getAccountNo());
        payTransfer.setInAccName(extOrder.getAccountName());
        payTransfer.setInSettleBankNo(extOrder.getBak1());
        payTransfer.setInBankNo(extOrder.getBak1());
        payTransfer.setInBankName(extOrder.getBak2());
        payTransfer.setMobileNo(extOrder.getMobileNo());
        payTransfer.setIdentityType(Constants.ID_CARD);
        payTransfer.setIdentityNo(extOrder.getIdCardNo());
        payTransfer.setAmount(extOrder.getAmount().subtract(extOrder.getFee()));
        payTransfer.setMerType(extOrder.getMerType());
        payTransfer.setMerNo(extOrder.getMerNo());

        boolean isTransferException = false;
        TransferOrder resTransfer = null;
        try {
            Transfer transfer = SpringUtil.getBean("transfer");
            resTransfer = transfer.pay(payTransfer);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("用户类型" + merType + "用户编号" + merNo + "提现订单" + extOrderNo + "发起提现接口异常" + e);
            isTransferException = true;
        }

        if (isTransferException) {
            //跟新提现订单记录和统一出账订单记录
            count = withdrawService.writeBackWithdrawInfo(withdrawOrderNo, Constants.WITHDRAW_STATUS_UNKNOW, null, null, "", "提现接口异常，状态未知");
            log.info("用户类型" + merType + "用户编号" + merNo + "提现接口异常，修改统一出账订单" + withdrawOrderNo + "状态未知影响的行数" + count);
            count = extractService.updateExtractStatus(extOrderNo, Constants.EXTRACT_STATUS_IN, null, Constants.EXTRACT_IS_NOT_REVERSE, "", "", "提现接口异常，状态未知");
            log.info("用户类型" + merType + "用户编号" + merNo + "提现接口异常，修改提现订单" + extOrderNo + "状态未知影响的行数" + count);

            return CommonResult.build(403, "提现中，请注意查看提现记录状态");
        }
        String transferOrderNo = resTransfer.getSubOrderNo();
        String transferOrderStatus = resTransfer.getStatus();
        String transferResCode = resTransfer.getResultCode();
        String transferResMsg = resTransfer.getResultMsg();

        log.info("用户类型" + merType + "用户编号" + merNo + "提现订单号" + extOrderNo + "对应出款平台返回记录transferOrderNo:{},transferOrderStatus:{}", new Object[]{transferOrderNo, transferOrderStatus});
        if (Constants.TRANSFER_STATUS_SUBMIT_FAIL.equals(transferOrderStatus) || Constants.TRANSFER_STATUS_FAIL.equals(transferOrderStatus)) {

            //跟新提现订单记录和统一出账订单记录
            count = withdrawService.writeBackWithdrawInfo(withdrawOrderNo, Constants.WITHDRAW_STATUS_FAIL, null, null, transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款失败，修改统一出账订单" + withdrawOrderNo + "状态失败影响的行数" + count);
            count = extractService.updateExtractStatus(extOrderNo, Constants.EXTRACT_STATUS_FAIL, null, Constants.EXTRACT_IS_NOT_REVERSE, "", transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款失败，修改提现订单" + extOrderNo + "状态失败影响的行数" + count);

            return CommonResult.build(403, "提现失败，请稍候再试");

        } else if (Constants.TRANSFER_STATUS_SUCCESS.equals(transferOrderStatus)) {

            //跟新提现订单记录和统一出账订单记录
            count = withdrawService.writeBackWithdrawInfo(withdrawOrderNo, Constants.WITHDRAW_STATUS_SUCCESS, null, transferOrderNo, transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款成功，修改统一出账订单" + withdrawOrderNo + "状态成功影响的行数" + count);
            count = extractService.updateExtractStatus(extOrderNo, Constants.EXTRACT_STATUS_SUCCESS, null, Constants.EXTRACT_IS_NOT_REVERSE, "", transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款成功，修改提现订单" + extOrderNo + "状态失败影响的行数" + count);

            return CommonResult.ok();

        } else {

            //跟新提现订单记录和统一出账订单记录
            count = withdrawService.writeBackWithdrawInfo(withdrawOrderNo, Constants.WITHDRAW_STATUS_UNKNOW, null, null, transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款未知，修改统一出账订单" + withdrawOrderNo + "状态未知影响的行数" + count);
            count = extractService.updateExtractStatus(extOrderNo, Constants.EXTRACT_STATUS_IN, null, Constants.EXTRACT_IS_NOT_REVERSE, "", transferResCode, transferResMsg);
            log.info("用户类型" + merType + "用户编号" + merNo + "提现出款未知，修改提现订单" + extOrderNo + "状态未知影响的行数" + count);

            return CommonResult.build(403, "提现中，请注意查看提现记录状态");
        }
    }
}
